package com.zhengtoudai.http;


import android.content.Context;
import android.text.TextUtils;

import com.google.gson.Gson;
import com.google.gson.GsonBuilder;
import com.google.gson.JsonObject;
import com.zhengtoudai.base.App;
import com.zhengtoudai.global.Config;
import com.zhengtoudai.ui.bean.AccountSettingModel;
import com.zhengtoudai.ui.bean.BorrowDetails;
import com.zhengtoudai.ui.bean.BorrowModel;
import com.zhengtoudai.ui.bean.DelegationNominis;
import com.zhengtoudai.ui.bean.HttpResult;
import com.zhengtoudai.ui.bean.Index;
import com.zhengtoudai.ui.bean.Login;
import com.zhengtoudai.ui.bean.MessageCenterModel;
import com.zhengtoudai.ui.bean.MyFragmentModel;
import com.zhengtoudai.ui.bean.MyInvestment;
import com.zhengtoudai.ui.bean.MyInvestmentMoldel;
import com.zhengtoudai.ui.bean.MyRedpacketModel;
import com.zhengtoudai.ui.bean.OnlyFinish;
import com.zhengtoudai.ui.bean.RedeemTransfer;
import com.zhengtoudai.ui.bean.Repossessed;
import com.zhengtoudai.ui.bean.Result;
import com.zhengtoudai.ui.bean.ShareRecordModel;
import com.zhengtoudai.ui.bean.ShengTenpay;
import com.zhengtoudai.ui.bean.TenderRecord;
import com.zhengtoudai.ui.bean.TransferDetail;
import com.zhengtoudai.ui.bean.TransferModel;
import com.zhengtoudai.util.Tool;

import java.util.HashMap;
import java.util.Map;

import javax.inject.Inject;

import okhttp3.OkHttpClient;
import retrofit2.Retrofit;
import retrofit2.adapter.rxjava.RxJavaCallAdapterFactory;
import retrofit2.converter.gson.GsonConverterFactory;
import rx.Observable;
import rx.Subscriber;
import rx.android.schedulers.AndroidSchedulers;
import rx.functions.Func1;
import rx.schedulers.Schedulers;


/**
 * ClassName: HttpApi<p>
 * Author: oubowu<p>
 * Fuction: Retrofit请求管理类<p>
 * CreateDate:2016/2/13 20:34<p>
 * UpdateUser:<p>
 * UpdateDate:<p>
 */
public class HttpApi {

    private HttpService mHttpService;
    @Inject
    OkHttpClient mOkHttpClient;
    @Inject
    Context mContext;

    private static HttpApi instance = null;

    /**
     * 获取单例
     *
     * @return 实例
     */
    public static HttpApi getInstance() {

        if (instance == null) {
            instance = new HttpApi();
            return instance;
        }

        return instance;

    }

    private HttpApi() {
        App.mApp.getAppComponent().inject(this);
        Gson gson=new GsonBuilder()
                .setDateFormat("yyyy-MM-dd HH:mm:ss")
                .create();
        Retrofit retrofit = new Retrofit.Builder()
                .baseUrl(Config.BASE_URL)
                .client(mOkHttpClient)
                .addConverterFactory(GsonConverterFactory.create(gson))
                .addCallAdapterFactory(RxJavaCallAdapterFactory.create())
                .build();
        
        mHttpService = retrofit.create(HttpService.class);
    }


    /*
    * 请求头信息
    * @return
    */
    public  static Map<String,String> getHeader() {

        Map<String,String> headers=new HashMap<>();
        if (!TextUtils.isEmpty(App.mApp.getSession().get("JSESSIONID"))){
            headers.put("JSESSIONID", App.mApp.getSession().get("JSESSIONID"));
        }
        if (!TextUtils.isEmpty(App.mApp.getSession().get("token"))){
            headers.put("token", App.mApp.getSession().get("token"));
        }
        headers.put("deviceId", Tool.getAppId(App.getContext()));
        headers.put("User-Agent", "android");
        headers.put("randomCode", Tool.getCharAndNumr(10));
        return headers;
    }

    /**
     * 处理线程
     * @param <T>
     * @return
     */
    private <T> Observable.Transformer<T,T> applySchedulers(){
        return new Observable.Transformer<T, T>() {
            @Override
            public Observable<T> call(Observable<T> tObservable) {
                return tObservable
                        .subscribeOn(Schedulers.io())
                        .observeOn(AndroidSchedulers.mainThread())
                        .unsubscribeOn(Schedulers.io());
            }
        };
    }


    /**
     *
     * <p/>
     * 对API调用了observeOn(MainThread)之后，线程会跑在主线程上，包括onComplete也是，
     * unsubscribe也在主线程，然后如果这时候调用call.cancel会导致NetworkOnMainThreadException
     * 加一句unsubscribeOn(io)
     *
            */

    /**
     * 获取短信验证码
     * @param mobile
     * @return
     */
    public Observable<Result> getSMSCode(String mobile){
        return mHttpService.getSMSCode(mobile)
                .compose(this.<Result>applySchedulers());
    }


    public Observable<MyFragmentModel> getAccount(){
        return mHttpService.getAccountIndex()
                .subscribeOn(Schedulers.io())
                .observeOn(AndroidSchedulers.mainThread())
                .unsubscribeOn(Schedulers.io());
    }

    public Observable<AccountSettingModel> getAccountSetting(){
        return mHttpService.getAccountSetting()
                .subscribeOn(Schedulers.io())
                .observeOn(AndroidSchedulers.mainThread())
                .unsubscribeOn(Schedulers.io());
    }

    public Observable<MessageCenterModel> getMessageCenter(String umPerPage,String pageNum){
        return mHttpService.getMessage(umPerPage,pageNum)
                .subscribeOn(Schedulers.io())
                .observeOn(AndroidSchedulers.mainThread())
                .unsubscribeOn(Schedulers.io());
    }

    public Observable<MyRedpacketModel> getMyRedpacket(String numPerPage, String pageNum){
        return mHttpService.getMyRedpacket(numPerPage,pageNum)
                .subscribeOn(Schedulers.io())
                .observeOn(AndroidSchedulers.mainThread())
                .unsubscribeOn(Schedulers.io());
    }

    public Observable<MyInvestmentMoldel> getMyInvestment(String numPerPage, String pageNum){
        return mHttpService.getMyInvestment(numPerPage,pageNum)
                .subscribeOn(Schedulers.io())
                .observeOn(AndroidSchedulers.mainThread())
                .unsubscribeOn(Schedulers.io());
    }

    public Observable<ShareRecordModel> getShareRecord(String numPerPage,String pageNum){
        return mHttpService.getShareRecord(numPerPage,pageNum)
                .subscribeOn(Schedulers.io())
                .observeOn(AndroidSchedulers.mainThread())
                .unsubscribeOn(Schedulers.io());
    }
    public Observable<BorrowModel> getBorrowList(Map<String,String> params){
        return mHttpService.getGetBorrowList(params)
                .subscribeOn(Schedulers.io())
                .observeOn(AndroidSchedulers.mainThread())
                .unsubscribeOn(Schedulers.io());
    }
    public Observable<TransferModel> getTransferList(Map<String,String> params){
        return mHttpService.getGetTransferList(params)
                .subscribeOn(Schedulers.io())
                .observeOn(AndroidSchedulers.mainThread())
                .unsubscribeOn(Schedulers.io());
    }



    private <T> void toSubscribe(Observable<T> o, Subscriber<T> s){
        o.subscribeOn(Schedulers.io())
                .unsubscribeOn(Schedulers.io())
                .observeOn(AndroidSchedulers.mainThread())
                .subscribe(s);
    }



    /**
     * 用来统一处理Http的resultCode,并将HttpResult的Data部分剥离出来返回给subscriber
     *
     * @param <T>   Subscriber真正需要的数据类型，也就是Data部分的数据类型
     *
     *
     */
    private class HttpResultFunc<T> implements Func1<HttpResult<T>, T> {

        @Override
        public T call(HttpResult<T> httpResult) {

            if (!httpResult.getCode().equals("0")) {
                throw new ApiException(httpResult.getMessage());
            }

            return httpResult.getSubjects();

        }
    }

    /**
     * 注册
     * @param params
     * @return
     */
    public Observable<Result> register(Map<String,String> params){
        return mHttpService.register(params)
                .compose(this.<Result>applySchedulers());
    }

    /**
     * 登陆
     * @param userAccount
     * @param userPassword
     * @return
     */
    public Observable<Result<Login>> login(String userAccount,String userPassword){
        return mHttpService.login(userAccount,userPassword)
                .compose(this.<Result<Login>>applySchedulers());
    }

    /**
     * 退出登录
     * @return
     */
    public Observable<Result> loginOut(){
        return mHttpService.loginOut().compose(this.<Result>applySchedulers());
    }

    /**
     * 忘记密码
     * @param userPhone
     * @param password
     * @param enterPassword
     * @param verifyCode
     * @return
     */
    public Observable<Result> forgerPassword(String userPhone,String password,String enterPassword,String verifyCode){
        return mHttpService.forgerPassword(userPhone,password,enterPassword,verifyCode)
                .compose(this.<Result>applySchedulers());
    }

    /**
     * 托管
     * @return
     */
    public Observable<ShengTenpay> getShengTenpay(String url){
        return mHttpService.getShengTenpay(url).compose(this.<ShengTenpay>applySchedulers());
    }

    /**
     * 托管
     * @return
     */
    public Observable<ShengTenpay> postShengTenpay(String url,Map<String,String> params){
        return mHttpService.postShengTenpay(url,params).compose(this.<ShengTenpay>applySchedulers());
    }

    public Observable<Result> changePassword(String oldPassword,String newPassword,String enterPassword){
        return mHttpService.changePassword(oldPassword, newPassword, enterPassword)
                .compose(this.<Result>applySchedulers());
    }

    /**
     * 债权转让
     * @param numPerPage
     * @param pageNum
     * @return
     */
    public Observable<DelegationNominis> borrowTransfer(int numPerPage,int pageNum){
        return mHttpService.borrowTransfer(numPerPage+"", pageNum+"")
                .compose(this.<DelegationNominis>applySchedulers());
    }

    public Observable<JsonObject> accountLog(Map<String,String> params){
        return mHttpService.accountLog(params)
                .compose(this.<JsonObject>applySchedulers());
    }

    public Observable<RedeemTransfer> redeemTransfer(String etenderId){
        return mHttpService.redeemTransfer(etenderId)
                .compose(this.<RedeemTransfer>applySchedulers());
    }

    public Observable<Result> requestTransfer(String transferMoney, String etenderId, String endTimeStr){
        return mHttpService.requestTransfer(transferMoney, etenderId, endTimeStr)
                .compose(this.<Result>applySchedulers());
    }

    /**
     * 首页信息
     * @return
     */
    public Observable<Result<Index>> getIndexBorrow(){
        return mHttpService.getIndexBorrow().compose(this.<Result<Index>>applySchedulers());
    }

    /**
     * 债权转让详情
     * @param borrowTransId
     * @return
     */
    public Observable<Result<TransferDetail>> TransferDetail(String borrowTransId){
        return mHttpService.TransferDetail(borrowTransId)
                .compose(this.<Result<TransferDetail>>applySchedulers());
    }

    public Observable<Result<BorrowDetails>> borrowDetail(String borrowEId){
        return mHttpService.borrowDetail(borrowEId)
                .compose(this.<Result<BorrowDetails>>applySchedulers());
    }

    public Observable<Result<TenderRecord>> tenderRecord(String borrowId){
        return mHttpService.tenderRecord(borrowId)
                .compose(this.<Result<TenderRecord>>applySchedulers());
    }

    public Observable<Result<TenderRecord>> offerToBuyRecord(String transferEId){
        return mHttpService.offerToBuyRecord(transferEId)
                .compose(this.<Result<TenderRecord>>applySchedulers());
    }

    public Observable<Result<MyInvestment>> myInvest(String numPerPage, String pageNum){
        return mHttpService.myInvest(numPerPage,pageNum)
                .compose(this.<Result<MyInvestment>>applySchedulers());
    }

    public Observable<Result<Repossessed>> getRepossessed(String numPerPage, String pageNum){
        return mHttpService.getRepossessed(numPerPage,pageNum)
                .compose(this.<Result<Repossessed>>applySchedulers());
    }
    public Observable<Result<OnlyFinish>> getOnlyFinish(String numPerPage, String pageNum){
        return mHttpService.getOnlyFinish(numPerPage,pageNum)
                .compose(this.<Result<OnlyFinish>>applySchedulers());
    }
}
